import simplejson

from sqlalchemy import *
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from optparse import OptionParser

from vote.model import *
from .base_controller import *

VERSION = "version 0.1 - May 2011"

class Voter(BaseController):
    ''' Voter is a class (sub'd from BaseController...which has db connection logic and some more db persist & query logic, which is called by Voter ... see below)
        whose methods represent services.  When hosted (exposed) through CherryPy, the methods that follow are call-able web services... 
    '''

    def index(self, feature=BOGUS_VALUE, type=BOGUS_VALUE, vote=BOGUS_VALUE, comment=None, user=BOGUS_VALUE, time=BOGUS_VALUE):
        ''' main entry point for the voter web service...this service is the meat of the app
            http://localhost:16111/vote/?... is the URL entry to this service

            different values for various params will make the service respond as a Create/Read

            rules:
                0. no parameters given, will list all features for all vote types, with their associated average
                1. one parameter - feature as the only parameter, the service responds with an average votes for just this feature
                2. one parameter - type as the only parameter, the service responds with an average of votes of this vote type for all features 
                3. one parameter - user as the only parameter, the service responds with an average of for all features that this user voted on
                4. combining feature, type, user will further filter the data based on those attributes and the rules above...
                5. passing a vote and a feature will insert that that vote into the database, with user defaulting to the default user and type defaulting to 1
                
            time parameter is used by the webapp to avoid service calls from being cached by the web browser (e.g., time makes urls look unique to browser cache)
        '''
        if vote is not None and vote is not BOGUS_VALUE and feature is not BOGUS_VALUE:
            response = self.new_vote(feature, type, vote, comment, user) or ERROR
        else:
            response = self.average_votes(feature, type, user) or ERROR

        return simplejson.dumps(response)


    def version(self):
        ''' simple read-only service that returns global VERSION string (above)
            http://localhost:16111/vote/version
        '''
        response = SUCCESS.copy()
        response["message"] = VERSION
        return simplejson.dumps(response)


    def types(self):
        ''' describe the different vote types in the db
            http://localhost:16111/vote/types
        '''
        response = SUCCESS.copy()
        try:
            response.setdefault('types', [])
            session = self.get_session()
            q = session.query(VoteType)
            for v in q:
                response['types'].append(v.to_dict())
        except Exception as detail:
            print detail
            response = ERROR.copy()
            response["message"] = "Error reading the database"
            response["detail"] = detail.__str__() 

        return simplejson.dumps(response)


    def votes(self, feature=BOGUS_VALUE, user=BOGUS_VALUE, has_comment=False, limit=20):
        ''' return the 'votes' objects as json, which will contain the comments
            optional parameters will shape & limit the output to a certain feature and/or certain user
            (see comment for method 'index' above for more on combining parameters).

            http://localhost:16111/vote/votes?...
        '''
        response = SUCCESS.copy()

        try:
            average = 0
            session = self.get_session()
            q = session.query(Vote)
            if user is not None and user is not BOGUS_VALUE:
                q = q.filter(Vote.user == user)
            if feature is not None and feature is not BOGUS_VALUE:
                q = q.filter(Vote.feature == feature)
            if has_comment:
                q = q.filter(Vote.comment != None)
            q = q.limit(limit)
            response.setdefault('votes', [])
            for v in q:
                response['votes'].append(v.to_dict())

        except Exception as detail:
            print detail
            response = ERROR.copy()
            response["message"] = "Error reading the database"
            response["detail"] = detail.__str__() 

        return simplejson.dumps(response)


    # list of services to expose
    index.exposed = True
    types.exposed = True
    votes.exposed = True
    version.exposed = True


'''
MAIN 
'''
def main():

    v = Voter(OPTIONS)
    r = v.index(1, 1, 3, " xxx ", 1)
    print r

    # average_all_features
    r = v.index()
    print r

    # average single feature
    r = v.index(None, 1, None, None, 1)
    print r

    # vote types
    r = v.types()
    print r

    # comments
    r = v.votes(1, 1)
    print r

    # comments
    r = v.version()
    print r


if __name__ == '__main__':
    main()

